package com.dmagic.cms.common.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.ClassPathResource;

/**
 * <h3>Class name</h3> Used to load the class resource file, under the ClassPath properties file. <h4>Description</h4>
 * getExtendResource(StringrelativePath) method, you can use the the ../ Symbol loading ClassPath external resources. <h4>
 * Special Notes</h4>
 * 
 * @ver 0.1
 * @author Jay.Wu 2008-11-24
 */
public class ClassLoaderUtil {

    private static Log logger = LogFactory.getLog(ClassLoaderUtil.class);

    /**
     * Thread.currentThread().getContextClassLoader().getResource("")
     */

    /**
     * @description :Java class is loaded. Use the fully qualified name of the class
     * @param className
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static Class loadClass(String className) {
        try {
            return getClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(" class not found ' " + className + " ' ", e);
        }
    }

    /**
     * @description : get Class loader
     * @return
     */
    public static ClassLoader getClassLoader() {
        return ClassLoaderUtil.class.getClassLoader();
    }

    /**
     * @description : To provide relative to the path of of ClassPath the resources, return file input stream
     * @param relativePath -Must pass the relative path of the resource.
     *  ClassPath relative to the path. If you need to find the ClassPath external resources, the need to use ../ to find
     * @return File input stream
     * @throws MalformedURLException
     * @throws IOException
     */
    public static InputStream getStream(String relativePath) throws MalformedURLException, IOException {
        if (!relativePath.contains("../")) {
            return getClassLoader().getResourceAsStream(relativePath);

        } else {
            return ClassLoaderUtil.getStreamByExtendResource(relativePath);
        }

    }

    /**
     * @description : get Input Stream
     * @param url 
     * @return
     * @throws IOException
     */
    public static InputStream getStream(URL url) throws IOException {
        if (url != null) {

            return url.openStream();

        } else {
            return null;
        }
    }

    /**
     * @description : get Input Stream By ExtendResource method.
     * @param relativePath -Relative path must transfer resources.
     *  ClassPath relative to the path. If you need to find the ClassPath external resources, the need to use ../ to find.
     * @return
     * @throws MalformedURLException
     * @throws IOException
     */
    public static InputStream getStreamByExtendResource(String relativePath) throws MalformedURLException, IOException {
        return ClassLoaderUtil.getStream(ClassLoaderUtil.getExtendResource(relativePath));

    }

    /**
     * @description :The the ClassLoader of Classpat of the Class where the absolute path. URL in the form of
     * @return
     */
    public static String getAbsolutePathOfClassLoaderClassPath() {
        logger.info(ClassLoaderUtil.getClassLoader().getResource("").toString());
        return ClassLoaderUtil.getClassLoader().getResource("").toString();
    }

    /**
     * @description : Get absolute path of the incoming resources
     * 
     * @param relativePath - You must pass the relative path of the resource. 
     *           ClassPath relative to the path. If you need to find the ClassPath external resources, the need to use ../ to find
     * @return The absolute URL of resources
     * @throws MalformedURLException
     */
    public static URL getExtendResource(String relativePath) throws MalformedURLException {

        logger.info("The relative path of the incoming ： " + relativePath);
        // ClassLoaderUtil.log.info(Integer.valueOf(relativePath.indexOf("../")))
        // ;
        if (!relativePath.contains("../")) {
            return ClassLoaderUtil.getResource(relativePath);
        }

        String classPathAbsolutePath = ClassLoaderUtil.getAbsolutePathOfClassLoaderClassPath();
        if (relativePath.substring(0, 1).equals("/")) {
            relativePath = relativePath.substring(1);
        }
        logger.info(Integer.valueOf(relativePath.lastIndexOf("../")));

        String wildcardString = relativePath.substring(0, relativePath.lastIndexOf("../") + 3);
        relativePath = relativePath.substring(relativePath.lastIndexOf("../") + 3);
        int containSum = ClassLoaderUtil.containSum(wildcardString, "../");
        classPathAbsolutePath = ClassLoaderUtil.cutLastString(classPathAbsolutePath, "/", containSum);
        String resourceAbsolutePath = classPathAbsolutePath + relativePath;
        logger.info("Absolute Path ： " + resourceAbsolutePath);
        URL resourceAbsoluteURL = new URL(resourceAbsolutePath);
        return resourceAbsoluteURL;
    }

    /**
     * @param source
     * @param dest
     * @return
     */
    private static int containSum(String source, String dest) {
        int containSum = 0;
        int destLength = dest.length();
        while (source.contains(dest)) {
            containSum = containSum + 1;
            source = source.substring(destLength);

        }

        return containSum;
    }

    /**
     * @param source
     * @param dest
     * @param num
     * @return
     */
    private static String cutLastString(String source, String dest, int num) {
        // String cutSource=null;
        for (int i = 0; i < num; i++) {
            source = source.substring(0, source.lastIndexOf(dest, source.length() - 2) + 1);

        }
        return source;
    }

    
    /**
     * @description : get Resource URL
     * @param resource -The incoming of the path relative to the ClassPath.
     * @return
     */
    public static URL getResource(String resource) {
        logger.info(" The incoming of the path relative to the ClassPath ： " + resource);
        return ClassLoaderUtil.getClassLoader().getResource(resource);
    }

    /**
     * @description : Spring class path resource
     * @param fileName
     * @return
     */
    public static String getClassesPath(String fileName) {
        // URL url = getResource(fileName);
        // String classPathName = url.getPath();
        // int endingIndex = classPathName.length() - fileName.length();
        // classPathName = classPathName.substring(0, endingIndex);
        ClassPathResource resource = new ClassPathResource(fileName);
        String path = "";
        try {
            path = resource.getURL().getPath().replace("%20", " ");
        } catch (Exception e) {
            logger.debug(e.getMessage(), e);
        }
        return path;
    }
}